﻿using NCalc;
using SqlSugar;
using System.Reflection;
using Zhp.Entity.Formula;
using Zhp.Entity.SysEnum;
using Zhp.IService.Formula;
using Zhp.IService.Formula.Attributes;
using Zhp.IService.Formula.VariableClass;
using Zhp.SqlSugar.Repository;
using Zhp.SqlSugar.UnitOfWork;

namespace Zhp.Service.Formula
{
    public class FormulaCalcService : IFormulaCalcService
    {
        private readonly string _separator = ";";
        ISqlSugarClient _dbContext;
        IFormulaVariableService _formulaVariableService;
        IBaseRepository<FormulaData> _formulaDataRep;
        IBaseRepository<FormulaVariable> _formulaVariableRep;
        public FormulaCalcService(IUnitOfWork<SugarUnitOfWork> unitOfWork, 
            IFormulaVariableService formulaVariableService, 
            IBaseRepository<FormulaData> formulaDataRep, 
            IBaseRepository<FormulaVariable> formulaVariableRep)
        {
            _dbContext = unitOfWork.Db;
            _formulaVariableService = formulaVariableService;
            _formulaDataRep = formulaDataRep;
            _formulaVariableRep = formulaVariableRep;
        }

        public async Task<decimal> Calc(IFormulaVariable formula)
        {
            var data = await _formulaDataRep.GetByIdAsync(formula.FormulaId);
            var variableIds = data.VariableIds.Split(_separator).ToList();
            var variableList = await _formulaVariableRep.GetListAsync(x => variableIds.Contains(x.Id.ToString()));

            var type = formula.GetType();
            // 创建一个新的表达式对象
            var expression = new Expression(data.FormulaKey);

            // 动态设置变量值
            foreach (var item in data.FormulaKeys.Split(_separator))
            {
                var variable = variableList.Find(x => x.VariableKey == item);
                if (variable != null && variable.VariableType == FormulaVariableTypeEnum.Variable)
                {
                    var objdata = type.GetProperty(variable.EntityField).GetValue(formula);
                    expression.Parameters[item] = objdata;
                }
            }

            // 计算并获取表达式的结果
            try
            {
                object result = expression.Evaluate();

                return Convert.ToDecimal(result);
            }
            catch (DivideByZeroException)
            {
                return 0;
            }
        }


        public async Task<decimal> Calc(long formulaId)
        {
            var formulaData = await _formulaDataRep.GetByIdAsync(formulaId);
            var variableIds = formulaData.VariableIds.Split(_separator).ToList();
            var variableList = await _formulaVariableRep.GetListAsync(x => variableIds.Contains(x.Id.ToString()));

            // 创建一个新的表达式对象
            var expression = new Expression(formulaData.FormulaKey);

            // 动态设置变量值
            foreach (var item in formulaData.FormulaKeys.Split(_separator))
            {
                var variable = variableList.Find(x => x.VariableKey == item);
                if (variable != null && variable.VariableType == FormulaVariableTypeEnum.Variable)
                {
                    if (!string.IsNullOrEmpty(variable.EntityType))
                    {
                        var type = _formulaVariableService.GetVariableClassType(variable.EntityType);
                        var data = await _dbContext.QueryableByObject(type).InSingleAsync(variable.VariablePrimaryKey);
                        var objdata = type.GetProperty(variable.EntityField).GetValue(data);
                        expression.Parameters[item] = objdata;
                    }
                    else
                    {
                        expression.Parameters[item] = 0;
                    }
                }
            }

            // 计算并获取表达式的结果
            try
            {
                object result = expression.Evaluate();

                return Convert.ToDecimal(result);
            }
            catch (DivideByZeroException)
            {
                return 0;
            }
        }
    }
}
